#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "public.h"
#include "userdb.h"
#include "clib/data_struct.h"

struct local_userdb *create_local_user(uid_t uid, gid_t gid, const char *login_name, int sockfd, pid_t pid)
{
	struct local_userdb *user = malloc(sizeof(struct local_userdb));
	
	if (!user)
		goto err;
	memset(user, 0, sizeof(struct local_userdb));
	user->uid = uid;
	user->gid = gid;
	strncpy(user->login_name, login_name, sizeof(user->login_name));
	user->sockfd = sockfd;
	user->pid = pid;
	return user;
err:
	if (user) {
		if (user->login_name)
			free(user->login_name);
		free(user);
	}
	return NULL;
}
void destroy_local_user(struct local_userdb *user)
{
	if (user) {
		if (user->login_name)
			free(user->login_name);
		free(user);
	}
}

lu_desc_t *local_user_open(void)
{
	lu_desc_t *ret = NULL;
	
	ret = (lu_desc_t *)malloc(sizeof(lu_desc_t));
	if (!ret) {
		goto end;
	}
	INIT_LIST_HEAD(&(ret->head));
	if (pthread_rwlock_init(&(ret->lu_lock), NULL) != 0) {
		free(ret);
		ret = NULL;
	}
end:
	return ret;
}

void local_user_add(lu_desc_t *lu_d, struct local_userdb *user)
{
	if (!lu_d || !user)
		return;
	pthread_rwlock_wrlock(&(lu_d->lu_lock));
	list_add(&(user->i_list), &(lu_d->head));
	pthread_rwlock_unlock(&(lu_d->lu_lock));
}

void local_user_del(lu_desc_t *lu_d, struct local_userdb *user)
{
	if (!lu_d || !user)
		return;
	pthread_rwlock_wrlock(&(lu_d->lu_lock));
	list_del(&(user->i_list));
	pthread_rwlock_unlock(&(lu_d->lu_lock));
	destroy_local_user(user);
}

void local_user_close(lu_desc_t *desc)
{
	struct list_head *ptr = NULL, *p[2] = {NULL, NULL};
	struct local_userdb *user = NULL;
	int i = 0;

	if (!desc)
		return;
	pthread_rwlock_wrlock(&(desc->lu_lock));
	list_for_each_prev(ptr, &(desc->head)) {
		p[i] = ptr;
		i = !i;
		if (p[i]) {
			user = list_entry(p[i], struct local_userdb, i_list);
			list_del(&(user->i_list));
			destroy_local_user(user);
		}
	}
	free(desc);
	pthread_rwlock_unlock(&(desc->lu_lock));
}
